package study_1;

/**
 * 线程的两种创建方式的区别
 * 1.Thread
 * 2.Runnable
 * 从对象共享的角度来看：
 *        第2种创建方式意味着多个线程实例可以共享同一个Runnable实例。在某些情况下可能导致程序的运行结果出乎我们的意料。
 *        例如，在如以下代码清单所示的程序中，我们分别以第2中和第1中方式各自创建了若干线程。
 *        假设这个程序运行在处理器个数为4的主机上，那么该程序的运行处中的“CountingTask：”后面跟的数字最大的数也可能仍小于800（=2*4*100），
 *        而“CountingThread：”后面跟的数字时钟都是100，对于这种结果的解释会涉及我们将在第2章中提到的竞态和线程安全这两个概念。
 */
public class Thread3 {
    public static void main(String[] args) {
        Thread t;
        CountingTask countingTask = new CountingTask();

        //获取处理器个数
        int numberOfProcessors = Runtime.getRuntime().availableProcessors();

        for (int i = 0; i < 2 * numberOfProcessors; i++) {
            //直接创建线程
            t = new Thread(countingTask);
            t.start();
        }

        for (int i = 0; i < 2 * numberOfProcessors; i++) {
            //以子类的方式创建线程
            t = new CountingThread();
            t.start();
        }
    }

    static class Counter{
        private int count = 0;

        public void increment(){
            count++;
        }

        public int value(){
            return count;
        }
    }

    static class CountingTask implements Runnable{
        private Counter counter = new Counter();

        @Override
        public void run(){
            for (int i = 0; i < 100; i++) {
                doSomething();
                counter.increment();
            }
            System.out.println("CountingTask:"+counter.value());
        }

        private void doSomething(){
            //使当前线程休眠随机时间
            Tools.randomPause(80);
        }
    }

    static class CountingThread extends Thread{
        private Counter counter = new Counter();

        @Override
        public void run(){
            for (int i = 0; i < 100; i++) {
                doSomething();
                counter.increment();
            }
            System.out.println("CountingThread:"+counter.value());
        }
        private void doSomething(){
            //使当前线程休眠随机时间
            Tools.randomPause(80);
        }
    }

    public static class Tools{
        private static void randomPause(long seconds){
            try {
                Thread.sleep(seconds);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}
